package vn.edu.saigontech.ncms.model.bookstore;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.OptimisticLockType;

import vn.edu.saigontech.ncms.model.BaseEntity;
import vn.edu.saigontech.ncms.model.enumeration.Currency;
import vn.edu.saigontech.ncms.model.info.OfferingMember;
import vn.edu.saigontech.ncms.model.system.Money;
import vn.edu.saigontech.ncms.model.user.User;
import vn.edu.saigontech.ncms.service.ItemTypeService;

@Entity
@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true, optimisticLock = OptimisticLockType.ALL)
@Table(name = "ncms_bookstore_order")
@SuppressWarnings("serial")
public class Order extends BaseEntity {
	
	@Column(name = "number")
	private String number;

	@Temporal(TemporalType.DATE)
	@Column(name = "date", nullable = false)
	private Date date;

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "order")
	@org.hibernate.annotations.Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
	@OrderBy
	private Set<OrderDetail> details;

	@ManyToOne
	@JoinColumn(name = "student_id")
	private OfferingMember student;

	@JoinColumn(name = "student_name")
	private String studentName;
	
	@Embedded
	@AttributeOverrides( {
			@AttributeOverride(name = "amount", column = @Column(name = "price_detail")),
			@AttributeOverride(name = "currency", column = @Column(name = "price_detail_currency")), })
	private Money totalPrice;

	@ManyToOne
	@JoinColumn(name = "cashier_id", nullable = false)
	private User cashier;

	@Column(name = "active")
	private boolean active;

	@Column(name = "comment", length = 4000)
	private String comment;
	
	public void increaseTotalPrice(OrderDetail detail) {
		double value = this.totalPrice.getAmount() + detail.getTotalPrice();
		this.setTotalPrice(new Money(value, Currency.VND));
	}
	
	public void decreaseTotalPrice(OrderDetail detail) {
		double value = this.totalPrice.getAmount() - detail.getTotalPrice();
		this.setTotalPrice(new Money(value, Currency.VND));
	}
	
	public List<ItemTitle> getItemTitles() {
		List<ItemTitle> ret = new ArrayList<ItemTitle>();
		for(OrderDetail detail : details) {
			ItemTitle title = detail.getItem().getItemTitle();
			if(!ret.contains(title)) {
				ret.add(title);
			}
		}
		return ret;
	}
	
	public Map<ItemType, Double> getPriceMap() {
		Map<ItemType, Double> map = this.createPriceMap();
		for(OrderDetail detail : details) {
			ItemType key = detail.getItem().getItemType();
			Double value = map.get(key);
			map.put(key, value + detail.getTotalPrice());
		}
		return map;
	}
	
	private Map<ItemType, Double> createPriceMap() {
		Map<ItemType, Double> ret = new HashMap<ItemType, Double>();
		Collection<ItemType> types = ItemTypeService.INSTANCE.findAll();
		for(ItemType type : types) {
			ret.put(type, 0.0);
		}
		return ret;
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	public Set<OrderDetail> getDetails() {
		return details;
	}

	public void setDetails(Set<OrderDetail> details) {
		this.details = details;
	}

	public OfferingMember getStudent() {
		return student;
	}

	public void setStudent(OfferingMember student) {
		this.student = student;
	}

	public User getCashier() {
		return cashier;
	}

	public void setCashier(User cashier) {
		this.cashier = cashier;
	}

	public boolean isActive() {
		return active;
	}

	public void setActive(boolean active) {
		this.active = active;
	}

	public String getComment() {
		return comment;
	}

	public void setComment(String comment) {
		this.comment = comment;
	}

	public String getStudentName() {
		return studentName;
	}

	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}

	public Money getTotalPrice() {
		return totalPrice;
	}

	public void setTotalPrice(Money totalPrice) {
		this.totalPrice = totalPrice;
	}
}